package com.hnust.root.service.impl.forward.wx;

import cn.hutool.core.lang.Console;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hnust.root.common.base.exception.BusinessException;
import com.hnust.root.common.constant.GlobalConstant;
import com.hnust.root.common.model.Code2sessionRes;
import com.hnust.root.common.util.ComUtil;
import com.hnust.root.common.util.JWTUtil;
import com.hnust.root.dao.entity.domain.forward.WxAccount;
import com.hnust.root.dao.mapper.wx.WxAccountMapper;
import com.hnust.root.service.forword.wx.WxAccountService;
import com.hnust.root.service.forword.wx.WxUserInfoService;
import com.hnust.root.web.shiro.JWTToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@Service
public class WxAccountServiceImp extends ServiceImpl<WxAccountMapper, WxAccount> implements WxAccountService {
    private static final Log LOGGER = LogFactory.get();

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private WxAccountMapper wxAccountMapper;

    @Autowired
    private JWTUtil jwtUtil;

    @Autowired
    private WxUserInfoService userInfoService;

    /**
     * 小程序appID
     */
    @Value("${wx.applet.appid}")
    private String appId;
    /**
     * 小程序secrte
     */
    @Value("${wx.applet.secret}")
    private String appSecrte;

    @Value("${TX.location.KEY}")
    private String txLocationKey;


    @Override
    public WxAccount getAccountByOpenId(String openId) {
        return wxAccountMapper.selectOne(new QueryWrapper<WxAccount>().eq("open_id", openId));
    }

    @Override
    public JWTToken wxLogin(String code) throws BusinessException {
        String resJsonStr = codeToSession(code);
        Code2sessionRes res = ComUtil.fromJson(resJsonStr, Code2sessionRes.class);

        if (res != null) {
            if (res.getErrcode().equals("0")) {
                WxAccount wxAccount = getAccountByOpenId(res.getOpenid());
                //新用户
                if (wxAccount == null) {
                    wxAccount = new WxAccount();
                    wxAccount.setOpenId(res.getOpenid());
                    LOGGER.info("新用户，此用户的openId为：" + res.getOpenid());
                }
                wxAccount.setSessionKey(res.getSession_key());
                wxAccount.setLastDate(LocalDateTime.now());
                //数据库保存用户信息
                saveOrUpdate(wxAccount);
                String token = jwtUtil.createTokenByWxAccount(wxAccount);
                return new JWTToken(token, res.getOpenid());
            } else {
                throw new BusinessException("微信code2Session失败！");
            }
        } else {
            throw new BusinessException("网络请求错误，无法根据code换取session");
        }
    }

    /***
     * 通过经纬度获取用户所在的城市
     * @param location ,经度 + 维度
     * @return
     */
    @Override
    public String getLocation(String location,String openId) {
        return getCityFromNet(location,openId);
    }


    /**
     * 通过code换取accesstoken
     * @param code
     * @return
     */
    private String codeToSession(String code) {
        String codeToSessionUrl = GlobalConstant.CODE_TO_SESSION_URL;
        Map<String, Object> params = new HashMap<>();
        params.put("appid", appId);
        params.put("secret",appSecrte);
        params.put("js_code",code);
        params.put("grant_type","authorization_code");

        Console.log("发送的请求为：" + params);
        String res = HttpUtil.get(codeToSessionUrl, params, 5000);
        Console.log("小程序登陆微信返回结果为：" + res);
        return res;
    }

    //通过TX地图接口获取用户地理位置信息
    private String getCityFromNet(String location,String openId) {
        String city = "未知";
        String url = GlobalConstant.TX_LOCATION_URL;
        Map<String, Object> params = new HashMap<>();
        params.put("location",location);
        params.put("key",txLocationKey);
        params.put("output","json");
        String result = HttpUtil.get(url, params, 5000);

        if (!StrUtil.isEmpty(result)) {
            try {
                JSONObject addressCompoent = JSONUtil.parseObj(result).getJSONObject("result").getJSONObject("address_component");
                String province = addressCompoent.getStr("province").replace("省", "");
                city = addressCompoent.getStr("city");

                if (!StrUtil.isEmpty(openId)) {
                    //更新用户省份及城市
                    userInfoService.updateUserInfo(openId, "province", province);
                    userInfoService.updateUserInfo(openId, "city", city);
                }
            } catch (Exception e) {
                LOGGER.info("通过经纬度获取地理信息位置时发生异常");
            }
        }
        return city;
    }
}
